package com.cc.blog.web.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.cc.blog.admin.mapper.ArticleCategoryRelMapper;
import com.cc.blog.admin.mapper.ArticleMapper;
import com.cc.blog.admin.mapper.CategoryMapper;
import com.cc.blog.admin.model.ArticleCategoryRelDO;
import com.cc.blog.admin.model.ArticleDO;
import com.cc.blog.admin.model.CategoryDO;
import com.cc.blog.common.enums.CodeEnum;
import com.cc.blog.common.exception.BusinessException;
import com.cc.blog.common.utils.PageResult;
import com.cc.blog.common.utils.Result;
import com.cc.blog.web.convert.ArticleConvert;
import com.cc.blog.web.domain.dto.FindCategoryArticlePageListReqDTO;
import com.cc.blog.web.domain.dto.FindCategoryListReqDTO;
import com.cc.blog.web.domain.vo.FindCategoryArticlePageListRspVO;
import com.cc.blog.web.domain.vo.FindCategoryListRspVO;
import com.cc.blog.web.service.CategoryService;
import com.google.common.collect.Lists;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * @Author cc
 * @Date 2024/7/12 10:50
 */
@Service
@Slf4j
@AllArgsConstructor
public class CategoryServiceImpl implements CategoryService {

    private final CategoryMapper categoryMapper;
    private final ArticleCategoryRelMapper articleCategoryRelMapper;
    private final ArticleMapper articleMapper;

    @Override
    public Result findCategoryList(FindCategoryListReqDTO findCategoryListReqDTO) {
        Long size = findCategoryListReqDTO.getSize();

        List<CategoryDO> categoryDOS = null;
        // 如果接口入参中未指定 size
        if (Objects.isNull(size) || size == 0) {
            // 查询所有分类
            categoryDOS = categoryMapper.selectList(Wrappers.emptyWrapper());
        } else {
            // 否则查询指定的数量
            categoryDOS = categoryMapper.selectByLimit(size);
        }
        // DO 转 VO
        List<FindCategoryListRspVO> vos = null;
        if (!CollectionUtils.isEmpty(categoryDOS)) {
            vos = categoryDOS.stream()
                    .map(categoryDO -> FindCategoryListRspVO.builder()
                            .id(categoryDO.getId())
                            .name(categoryDO.getName())
                            .articlesTotal(categoryDO.getArticlesTotal())
                            .build())
                    .collect(Collectors.toList());
        }
        return Result.success(vos);
    }

    @Override
    public Result findCategoryArticlePageList(FindCategoryArticlePageListReqDTO findCategoryArticlePageListReqDTO) {
        Long current = findCategoryArticlePageListReqDTO.getCurrent();
        Long size = findCategoryArticlePageListReqDTO.getSize();
        Long categoryId = findCategoryArticlePageListReqDTO.getId();
        CategoryDO categoryDO = categoryMapper.selectById(categoryId);
        // 判断该分类是否存在
        if (Objects.isNull(categoryDO)) {
            log.warn("==> 该分类不存在, categoryId: {}", categoryId);
            throw new BusinessException(CodeEnum.CATEGORY_NOT_EXISTED);
        }
        Page page = new Page<>(current, size);
        // 先查询该分类下所有关联的文章 ID
        List<ArticleCategoryRelDO> articleCategoryRelDOS = articleCategoryRelMapper.selectList(
                Wrappers.<ArticleCategoryRelDO>lambdaQuery().eq(ArticleCategoryRelDO::getCategoryId,categoryId));
        // 若该分类下未发布任何文章
        if (CollectionUtils.isEmpty(articleCategoryRelDOS)) {
            log.info("==> 该分类下还未发布任何文章, categoryId: {}", categoryId);
            return PageResult.success(page, Lists.newArrayList());
        }
        List<Long> articleIds = articleCategoryRelDOS.stream().map(ArticleCategoryRelDO::getArticleId).collect(Collectors.toList());
        // 根据文章 ID 集合查询文章分页数据
        LambdaQueryWrapper<ArticleDO> queryWrapper = Wrappers.<ArticleDO>lambdaQuery().in(ArticleDO::getId, articleIds).orderByDesc(ArticleDO::getCreateTime);
        Page<ArticleDO> ipage = articleMapper.selectPage(page, queryWrapper);
        List<ArticleDO> articleDOS = ipage.getRecords();
        // DO 转 VO
        List<FindCategoryArticlePageListRspVO> vos = null;
        if (!CollectionUtils.isEmpty(articleDOS)) {
            vos = articleDOS.stream()
                    .map(ArticleConvert.INSTANCE::convertDO2CategoryArticleVO)
                    .collect(Collectors.toList());
        }
        return PageResult.success(page, vos);
    }
}
